﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.LIB;
using YArchitech.MEP.Electric.Common;
using YArchitech.Revit;
using YArchitech.Revit.Electric;
using YArchitech.Revit.Electric.Common;
using HYElectricSetting;

namespace HYRElectric.WirePlace
{
	public class PanelOutLine : HYCmdEntry
	{
		public PanelOutLine(ExternalCommandData commandData) : base(commandData)
		{
		}

		public bool Excute()
		{
			bool result;
			try
			{
				RevitVersionFuncs.ClearSelection(this.m_sel);
				this.scale = this.m_doc.ActiveView.Scale;
				ISelectionFilter selectionFilter = new RevitFilter.PanelFilter();
				Reference reference = this.m_sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, selectionFilter, "选择配电箱的边缘线");
				FamilyInstance familyInstance = this.m_doc.GetElement(reference) as FamilyInstance;
				this.panelConn = RevitUtils.GetDeviceConnector(familyInstance);
				XYZ globalPoint = reference.GlobalPoint;
				using (DlgPanelOutLine dlgPanelOutLine = new DlgPanelOutLine(this.m_doc))
				{
					if (dlgPanelOutLine.ShowDialog() == DialogResult.OK)
					{
						double num = Convert.ToDouble(dlgPanelOutLine.nudWireNum.Text);
						double size = AssistFunc.mmToFeet(Convert.ToDouble(dlgPanelOutLine.nudWireLength.Text));
						Dictionary<Curve, XYZ> panelEdgeDirection = this.GetPanelEdgeDirection(familyInstance, globalPoint);
						Curve curve = panelEdgeDirection.Keys.First<Curve>();
						XYZ direction = panelEdgeDirection.Values.First<XYZ>();
						double num2;
						if (dlgPanelOutLine.rdoSpecifyDistance.Checked)
						{
							num2 = AssistFunc.mmToFeet(Convert.ToDouble(dlgPanelOutLine.nudSpecifyDistance.Text));
						}
						else
						{
							num2 = curve.Length / num;
						}
						LineInfo lineInfo = this.GetLineInfo(curve);
						XYZ middlePt = lineInfo.MiddlePt;
						XYZ xyz = lineInfo.Vector.Normalize();
						Transaction transaction = new Transaction(this.m_doc, "PanelOutLine");
						transaction.Start();
						if (num % 2.0 == 0.0)
						{
							XYZ xyz2 = middlePt + xyz * (num2 / 2.0);
							XYZ xyz3 = middlePt + -xyz * (num2 / 2.0);
							this.DrawingWire(xyz2, direction, size);
							this.DrawingWire(xyz3, direction, size);
							int num3 = 0;
							while ((double)num3 < num - 2.0)
							{
								xyz2 += xyz * num2;
								xyz3 += -xyz * num2;
								this.DrawingWire(xyz2, direction, size);
								this.DrawingWire(xyz3, direction, size);
								num3 += 2;
							}
						}
						else
						{
							XYZ xyz2 = middlePt;
							XYZ xyz3 = middlePt;
							if (xyz2.IsAlmostEqualTo(xyz3))
							{
								this.DrawingWire(xyz2, direction, size);
							}
							else
							{
								this.DrawingWire(xyz2, direction, size);
								this.DrawingWire(xyz3, direction, size);
							}
							int num4 = 0;
							while ((double)num4 < num - 1.0)
							{
								xyz2 += xyz * num2;
								xyz3 += -xyz * num2;
								this.DrawingWire(xyz2, direction, size);
								this.DrawingWire(xyz3, direction, size);
								num4 += 2;
							}
						}
						transaction.Commit();
					}
				}
				result = true;
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = true;
			}
			catch (Exception)
			{
				TaskDialog.Show("盈建科提示", "箱柜出线失败，请检查配电箱族是否与盈建科软件自带配电箱族一致。");
				result = false;
			}
			return result;
		}

		private void DrawingWire(XYZ start, XYZ direction, double size)
		{
			WireType wireType = this.GetWireType();
			if (wireType == null)
			{
				wireType = (RevitFilter.GetElementsOfType(this.m_doc, typeof(WireType)).ToList<Element>()[0] as WireType);
			}
            Wire wire = HyRevitUtils.CreateWire(this.m_doc, wireType, this.m_doc.ActiveView, (Autodesk.Revit.DB.Electrical.WiringType)1, start, direction, size, this.panelConn, null);
			this.AssignParameters(wire);
		}

		private WireType GetWireType()
		{
			WireType result = null;
			List<RevitWireType> list = new List<RevitWireType>();
			YArchitech.MEP.Electric.Common.XmlHelper xmlHelper = new YArchitech.MEP.Electric.Common.XmlHelper();
			string xmlPath = Path.Combine(Product.WorkingLocation, "ConnectWire.xml");
			xmlHelper.LoadXml(xmlPath, "Root");
			xmlHelper.SelectNode(Path.Combine("Root", "HYConnectWire", "Params"));
			list = ElectricSettingDataAssist.GetRevitWireTypes(this.m_doc);
			if (list.Count == 0)
			{
				return result;
			}
			string attribute = xmlHelper.GetAttribute("WireType");
			if (!string.IsNullOrEmpty(attribute))
			{
				foreach (RevitWireType revitWireType in list)
				{
					if (revitWireType.Name == attribute)
					{
						result = (this.m_doc.GetElementById(revitWireType.WireTypeId) as WireType);
						break;
					}
				}
			}
			return result;
		}

		private bool AssignParameters(Wire wire)
		{
			bool result;
			try
			{
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_TICKMARK_STATE).Set(2);
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_HOT_ADJUSTMENT).Set(WireConnectForm.wireParams.WireNum);
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_GROUND_ADJUSTMENT).Set(1);
				wire.get_Parameter(BuiltInParameter.RBS_ELEC_WIRE_NEUTRAL_ADJUSTMENT).Set(1);
				this.AddSharedParamsForWire(wire);
				result = true;
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
				result = false;
			}
			return result;
		}

		private void AddSharedParamsForWire(Wire wire)
		{
			CmdSetValueToWire.AddSharedParamsToWire(this.m_doc, wire);
		}

		private Dictionary<Curve, XYZ> GetPanelEdgeDirection(FamilyInstance panel, XYZ refPoint)
		{
			List<Curve> deviceEdgeCurves = new EquipmentEdgeLine(this.m_doc).GetDeviceEdgeCurves(panel);
			refPoint = new XYZ(refPoint.X, refPoint.Y, 0.0);
			Dictionary<Curve, XYZ> dictionary = new Dictionary<Curve, XYZ>();
			List<Curve> list = new List<Curve>();
			foreach (Curve curve in deviceEdgeCurves)
			{
				if (list.Count > 0)
				{
					if (Math.Abs(list[0].Length - curve.Length) < 0.0001)
					{
						list.Add(curve);
					}
				}
				else
				{
					list.Add(curve);
				}
				if (list.Count == 2)
				{
					break;
				}
			}
			XYZ xyz = ((list[0].GetEndPoint(0) + list[0].GetEndPoint(1)) / 2.0 + (list[1].GetEndPoint(0) + list[1].GetEndPoint(1)) / 2.0) / 2.0;
			Curve curve2 = null;
			foreach (Curve curve3 in deviceEdgeCurves)
			{
				if (curve3.Distance(refPoint) < 0.0001)
				{
					curve2 = curve3;
					break;
				}
			}
			if (curve2 == null)
			{
				Curve curve4 = (deviceEdgeCurves[0].Project(refPoint).Distance < deviceEdgeCurves[1].Project(refPoint).Distance) ? deviceEdgeCurves[0] : deviceEdgeCurves[1];
				Curve curve5 = (deviceEdgeCurves[2].Project(refPoint).Distance < deviceEdgeCurves[3].Project(refPoint).Distance) ? deviceEdgeCurves[2] : deviceEdgeCurves[3];
				curve2 = ((curve4.Project(refPoint).Distance < curve5.Project(refPoint).Distance) ? curve4 : curve5);
			}
			XYZ value = (curve2.Project(xyz).XYZPoint - xyz).Normalize();
			dictionary.Add(curve2, value);
			return dictionary;
		}

		private LineInfo GetLineInfo(Curve line)
		{
			return new LineInfo
			{
				StartPt = line.GetEndPoint(0),
				EndPt = line.GetEndPoint(1),
				MiddlePt = (line.GetEndPoint(0) + line.GetEndPoint(1)) / 2.0,
				Vector = line.GetEndPoint(1) - line.GetEndPoint(0)
			};
		}

		private int scale;

		private XYZ panelLocation;

		private Connector panelConn;
	}
}
